#include "RXSceneComponent.h"

BeginMetaData(RXSceneComponent)

META_BEGIN_CONSTRUCTOR(RXNodeCreationInfo*)
META_END_CONSTRUCTOR

META_BEGIN_PROPERTY(Rotation)
META_ADD_GETTER(GetRotation)
META_ADD_SETTER(SetRotation)
META_ADD_NOTIFIER(RotationChanged)
META_END_PROPERTY

META_BEGIN_PROPERTY(Postion)
META_ADD_GETTER(GetPostion)
META_ADD_SETTER(SetPostion)
META_ADD_NOTIFIER(PositionChanged)
META_END_PROPERTY

META_BEGIN_PROPERTY(Scale)
META_ADD_GETTER(GetScale)
META_ADD_SETTER(SetScale)
META_ADD_NOTIFIER(ScaleChanged)
META_END_PROPERTY

META_BEGIN_PROPERTY(Matrix)
META_ADD_GETTER(GetMatrix)
META_ADD_SETTER(SetMatrix)
META_END_PROPERTY

META_BEGIN_SIGNAL(RotationChanged)
META_END_SIGNAL

META_BEGIN_SIGNAL(PositionChanged)
META_END_SIGNAL

META_BEGIN_SIGNAL(ScaleChanged)
META_END_SIGNAL

EndMetaData


RXSceneComponent::RXSceneComponent(RXNodeCreationInfo* info) :SuperType(info), m_rotation{ 1,0,0,0 }, m_pos{ 0,0,0 }, m_scale{ 1,1,1 }{
	m_matrix.setIdentity();
}

RXSceneComponent::~RXSceneComponent() {

}

void RXSceneComponent::SetRotation(QuaternionD q)
{
	if (q != m_rotation) {
		m_rotation = q;
		UpdateToMatrix();
		RotationChanged(q);
	}
}

QuaternionD RXSceneComponent::GetRotation() const
{
	return m_rotation;
}

void RXSceneComponent::SetPostion(Vector3D pos)
{
	if (m_pos != pos) {
		m_pos = pos;
		UpdateToMatrix();
		PositionChanged(pos);
	}
	
}

Vector3D RXSceneComponent::GetPostion() const
{
	return m_pos;
}

void RXSceneComponent::SetScale(Vector3D scale)
{
	if (m_scale != scale) {
		m_scale = scale;
		UpdateToMatrix();
		ScaleChanged(scale);
	}
}

Vector3D RXSceneComponent::GetScale() const
{
	return m_scale;
}

void RXSceneComponent::SetMatrix(Matrix4D mat)
{
	if (m_matrix != mat) {
		m_matrix = mat;
		UpdateFromMatrix();
		RotationChanged(m_rotation);
		PositionChanged(m_pos);
		ScaleChanged(m_scale);
	}
}

Matrix4D RXSceneComponent::GetMatrix() const
{
	return m_matrix;
}

Matrix4D RXSceneComponent::GetWorldMatrix() const
{
	//TODO

	const RXTree* p = this;

	Matrix4D current;
	current.setIdentity();

	while (true)
	{
		if (p == NULL) {
			break;
		}

		const RXSceneComponent* comp = dynamic_cast<const RXSceneComponent*>(p);
		if (comp)
		{
			current = comp->m_matrix;
		}

		p = p->GetParent();
	}



	return current;
}

void RXSceneComponent::UpdateToMatrix()
{
	m_matrix = Compose(m_pos, m_scale, m_rotation);
}

void RXSceneComponent::UpdateFromMatrix()
{
	Decompose(m_matrix, m_pos, m_scale, m_rotation);
}
